/*
Module : SERIALPORT.H
Purpose: Declaration for an MFC wrapper class for serial ports
Created: PJN / 31-05-1999
History: None

Copyright (c) 1999 by PJ Naughter.  
All rights reserved.

*/



///////////////////// Macros / Structs etc //////////////////////////

#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__





/////////////////////////// Classes ///////////////////////////////////////////


////// Serial port exception class ////////////////////////////////////////////

//void AfxThrowSerialException(DWORD dwError = 0);
//
//class CSerialException : public CException
//{
//public:
////Constructors / Destructors
//	CSerialException(DWORD dwError);
//	~CSerialException();
//
////Methods
//#ifdef _DEBUG
//	virtual void Dump(CDumpContext& dc) const;
//#endif
//	virtual BOOL GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,	PUINT pnHelpContext = NULL);
//	CString GetErrorMessage();
//
////Data members
//	DWORD m_dwError;
//
//protected:
//	DECLARE_DYNAMIC(CSerialException)
//};
//
//

//// The actual serial port class /////////////////////////////////////////////



class CSerialPort : public CObject
{
public:
	//Enums
	enum FlowControl
	{
		NoFlowControl,
		CtsRtsFlowControl,
		CtsDtrFlowControl,
		DsrRtsFlowControl,
		DsrDtrFlowControl,
		XonXoffFlowControl
	};

	enum Parity
	{    
		NoParity,
		OddParity,
		EvenParity,
		MarkParity,    
		SpaceParity
	};
	enum StopBits
	{
		OneStopBit,
		OnePointFiveStopBits,
		TwoStopBits
	};

//Constructors / Destructors
  CSerialPort();
  ~CSerialPort();

//General Methods
  bool Open(int nPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE DataBits = 8, 
            StopBits stopbits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
  void Close();
  void Attach(HANDLE hComm);
  HANDLE Detach();
  operator HANDLE() const { return m_hComm; };
  BOOL IsOpen() const { return m_hComm != INVALID_HANDLE_VALUE; };
#ifdef _DEBUG
  void CSerialPort::Dump(CDumpContext& dc) const;
#endif

//Reading / Writing Methods
  DWORD Read(void* lpBuf, DWORD dwCount);
  BOOL Read(void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped);
  bool ReadEx(void* lpBuf, DWORD dwCount);
  DWORD Write(const void* lpBuf, DWORD dwCount);
  BOOL Write(const void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped);
  bool WriteEx(const void* lpBuf, DWORD dwCount);
  bool TransmitChar(char cChar);
  bool GetOverlappedResult(OVERLAPPED& overlapped, DWORD& dwBytesTransferred, BOOL bWait);
  bool CancelIo();

//Configuration Methods
  bool GetConfig(COMMCONFIG& config);
  static bool GetDefaultConfig(int nPort, COMMCONFIG& config);
  bool SetConfig(COMMCONFIG& Config);
  static bool SetDefaultConfig(int nPort, COMMCONFIG& config);

//Misc RS232 Methods
  bool ClearBreak();
  bool SetBreak();
  bool ClearError(DWORD& dwErrors);
  bool GetStatus(COMSTAT& stat);
  bool GetState(DCB& dcb);
  bool SetState(DCB& dcb);
  bool Escape(DWORD dwFunc);
  void ClearDTR();
  void ClearRTS();
  void SetDTR();
  void SetRTS();
  void SetXOFF();
  void SetXON();
  bool GetProperties(COMMPROP& properties);
  bool GetModemStatus(DWORD& dwModemStatus); 

//Timeouts
  bool SetTimeouts(COMMTIMEOUTS& timeouts);
  bool GetTimeouts(COMMTIMEOUTS& timeouts);
  void Set0Timeout();
  void Set0WriteTimeout();
  void Set0ReadTimeout();

//Event Methods
  bool SetMask(DWORD dwMask);
  bool GetMask(DWORD& dwMask);
  bool WaitEvent(DWORD& dwMask);
  bool WaitEvent(DWORD& dwMask, OVERLAPPED& overlapped);
  
//Queue Methods
  bool Flush();
  bool Purge(DWORD dwFlags);
  void TerminateOutstandingWrites();
  void TerminateOutstandingReads();
  void ClearWriteBuffer();
  void ClearReadBuffer();
  bool Setup(DWORD dwInQueue, DWORD dwOutQueue);

//Overridables
  virtual void OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped);

protected:
  HANDLE m_hComm;       //Handle to the comms port
  BOOL   m_bOverlapped; //Is the port open in overlapped IO

  static void WINAPI _OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped); 

	DECLARE_DYNAMIC(CSerialPort)
};


#endif //__SERIALPORT_H__